package com.cnap.multiclouldmgmt.service.impl;

import cn.hutool.core.collection.ConcurrentHashSet;
import com.cnap.multiclouldmgmt.model.AccountInfo;
import com.cnap.multiclouldmgmt.model.RepByPage;
import com.cnap.multiclouldmgmt.model.flavor.FlavorInfo;
import com.cnap.multiclouldmgmt.model.gpu.FlavorGPUInfoWithImageDisk;
import com.cnap.multiclouldmgmt.model.k8sModels.*;
import com.cnap.multiclouldmgmt.model.microSvc.MicroServicePO;
import com.cnap.multiclouldmgmt.repository.master.FlavorInfoMapper;
import com.cnap.multiclouldmgmt.service.CacheService;
import com.cnap.multiclouldmgmt.service.MultiCloudMgmtService;
import com.cnap.multiclouldmgmt.util.CnapCloudMgmtConstants;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service("CacheServiceImpl")
public class CacheServiceImpl implements CacheService {

    private final static Logger LOGGER = LoggerFactory.getLogger(CacheServiceImpl.class);

    private static final Map<String,KubernetesClient> k8sClusterClientMap = new ConcurrentHashMap<>();

    public static final Map<String,List<EventModel>> k8sClusterEventMap = new ConcurrentHashMap<>();

    public static final Map<String,K8sClusterBasicModel> k8sClusterBasicModelMap = new ConcurrentHashMap<>();

    public static final Map<String,Long> vmCreateSvcInfo = new ConcurrentHashMap<>();

    public static final Map<String,Map<String,RepByPage<NodeModel>>> k8sClusterNodeInfoMap = new ConcurrentHashMap<>();

    public static final Map<String,Map<String,RepByPage<NameSpaceModel>>> k8sClusterNsInfoMap = new ConcurrentHashMap<>();

    public static final Map<String,Map<String,RepByPage<WorkLoadModel>>> k8sClusterWorkLoadInfoMap = new ConcurrentHashMap<>();

    public static final Map<String,Map<String,RepByPage<PodModel>>> k8sClusterPodInfoMap = new ConcurrentHashMap<>();

    public static final Map<String,Map<String,RepByPage<SvcModel>>> k8sClusterSvcInfoMap = new ConcurrentHashMap<>();

    public static final Map<String,FlavorInfo> flavorInfoMap = new ConcurrentHashMap<>();

    public static final Map<String,Map<String,K8sClusterModel>> k8sClusterModelMap= new ConcurrentHashMap<>();

    public static final Map<String,Map<String, MicroServicePO>> microSvcInfoMap= new ConcurrentHashMap<>();

    public static final Map<String,SvcModel> svcModelForMicroInfoMap = new ConcurrentHashMap<>();

    public static final Set<String> stopSvcIdSet = new ConcurrentHashSet<>();

    public static final Map<String, FlavorGPUInfoWithImageDisk> gpuFlavorInfoMap = new ConcurrentHashMap<>();


    public static final Map<String, AccountInfo> netAccountMap = new ConcurrentHashMap<>();

    @Autowired
    private FlavorInfoMapper flavorInfoMapper;

    @Override
    public AccountInfo getAccountNameByNetName(String netName) {

        if (StringUtils.isEmpty(netName)){
            return null;
        }

        if (netAccountMap.containsKey(netName)){
            return netAccountMap.get(netName);
        }

        List<AccountInfo> accountInfos = flavorInfoMapper.getAllAccount();
        if ((accountInfos != null)&&(!accountInfos.isEmpty())){
            for (AccountInfo accountInfo:accountInfos){
                if (StringUtils.isNotBlank(accountInfo.getNetName())) {
                    netAccountMap.put(accountInfo.getAccountName(), accountInfo);

                    if (StringUtils.equalsIgnoreCase(accountInfo.getNetName(),netName)){
                        return accountInfo;
                    }
                }

            }
        }

        return null;
    }

    @Override
    public void putGpuFlavorInfo(String key, FlavorGPUInfoWithImageDisk flavorGPUInfoWithImageDisk) {
        gpuFlavorInfoMap.put(key,flavorGPUInfoWithImageDisk);
    }

    @Override
    public FlavorGPUInfoWithImageDisk getGpuFlavorInfo(String key) {
        return gpuFlavorInfoMap.get(key);
    }

    @Override
    public void putStopVmCreateSvc(String svcId) {
        stopSvcIdSet.add(svcId);
    }

    @Override
    public boolean checkSvcIdWhetherStop(String svcId) {

        if (!stopSvcIdSet.isEmpty()){
            return stopSvcIdSet.contains(svcId);
        }

        return false;
    }

    @Override
    public void removeStopSvcId(String svcId) {
        stopSvcIdSet.remove(svcId);
    }

    @Override
    public List<SvcModel> getSvcModelsForMicroSvc() {
        if (svcModelForMicroInfoMap.isEmpty()){
            return new ArrayList<>();
        }
        return new ArrayList<>(svcModelForMicroInfoMap.values());
    }

    @Override
    public void putSvcModelForMicroSvc(String ipSvcName, SvcModel svcModel) {
        svcModelForMicroInfoMap.put(ipSvcName,svcModel);
    }

    @Override
    public SvcModel getSvcModelByIpSvcName(String ipSvcName) {
        return svcModelForMicroInfoMap.get(ipSvcName);
    }

    @Override
    public MicroServicePO getMicroSvc(String userName, String serviceName) {

        if (microSvcInfoMap.get(userName) == null){
            return null;
        }

        return microSvcInfoMap.get(userName).get(serviceName);
    }

    @Override
    public void putMicroSvc(String userName, MicroServicePO microServicePO) {

        microSvcInfoMap.computeIfAbsent(userName, k -> new HashMap<>());

        microSvcInfoMap.get(userName).put(microServicePO.getServiceName(),microServicePO);
    }

    @Override
    public void cleanAllMicroSvcCache() {
        microSvcInfoMap.clear();
        svcModelForMicroInfoMap.clear();
    }

    @Override
    public List<K8sClusterModel> getAllK8sClusterModels(String createUser) {

        if (k8sClusterModelMap.isEmpty()) {
            return new ArrayList<>();
        }

        return new ArrayList<>(k8sClusterModelMap.get(createUser).values());
    }

    @Override
    public void putK8sClusterModels(String createUser, K8sClusterModel k8sClusterModel) {
        if (!k8sClusterModelMap.containsKey(createUser)){
            k8sClusterModelMap.put(createUser,new HashMap<>());
        }

        k8sClusterModelMap.get(createUser).put(k8sClusterModel.getK8sClusterName(),k8sClusterModel);
    }

    @Override
    public List<String> getK8sClusterNames(String userName) {

        Map<String,RepByPage<NodeModel>> nodeInfoMap
                    = k8sClusterNodeInfoMap.get(userName);
        if ((nodeInfoMap == null)
                ||(nodeInfoMap.isEmpty())){
            return new ArrayList<>();
        }

        return new ArrayList<>(nodeInfoMap.keySet());
    }

    @Override
    public List<String> getAllK8sUser() {

        if (k8sClusterNodeInfoMap.isEmpty()){
            return new ArrayList<>();
        }

        return new ArrayList<>(k8sClusterNodeInfoMap.keySet());
    }

    @Override
    public void clearAllK8sInfoCache() {

        k8sClusterNodeInfoMap.clear();
        k8sClusterNsInfoMap.clear();
        k8sClusterWorkLoadInfoMap.clear();
        k8sClusterPodInfoMap.clear();
        k8sClusterSvcInfoMap.clear();
    }

    @Override
    public void clearK8sInfoCache(String createUser, String clusterName) {
        if ((k8sClusterNodeInfoMap.containsKey(createUser))) {
            k8sClusterNodeInfoMap.get(createUser).remove(clusterName);
        }
        if (k8sClusterNsInfoMap.containsKey(createUser)) {
            k8sClusterNsInfoMap.get(createUser).remove(clusterName);
        }
        if (k8sClusterWorkLoadInfoMap.containsKey(createUser)) {
            k8sClusterWorkLoadInfoMap.get(createUser).remove(clusterName);
        }
        if (k8sClusterPodInfoMap.containsKey(createUser)) {
            k8sClusterPodInfoMap.get(createUser).remove(clusterName);
        }
        if (k8sClusterSvcInfoMap.containsKey(createUser)) {
            k8sClusterSvcInfoMap.get(createUser).remove(clusterName);
        }
        if (k8sClusterModelMap.containsKey(createUser)){
            k8sClusterModelMap.get(createUser).remove(clusterName);

        }
    }

    @Autowired
    private MultiCloudMgmtService multiCloudMgmtService;

    @Override
    public void putFlavorInfo(String key, FlavorInfo flavorInfo) {

        flavorInfoMap.put(key,flavorInfo);
    }

    @Override
    public FlavorInfo getFlavorInfo(String key) {
        return flavorInfoMap.get(key);
    }

    @Override
    public void putK8sSvcInfo(String createUser, RepByPage<SvcModel> svcModelRepByPage) {
        if (svcModelRepByPage.getTotalNum() == 0){
            return;
        }

        if (!k8sClusterSvcInfoMap.containsKey(createUser)){
            k8sClusterSvcInfoMap.put(createUser,new HashMap<>());
        }

        k8sClusterSvcInfoMap.get(createUser).put(
                svcModelRepByPage.getResult().get(0).getK8sClusterName(),
                svcModelRepByPage);
    }

    @Override
    public List<RepByPage<SvcModel>> getK8sSvcInfo(String createUser) {

        if (StringUtils.equals(createUser,CnapCloudMgmtConstants.ADMIN_USER_NAME)){
            List<RepByPage<SvcModel>> result = new ArrayList<>();
            if (!k8sClusterSvcInfoMap.isEmpty()){

                for (String userName:k8sClusterSvcInfoMap.keySet()){
                    result.addAll(k8sClusterSvcInfoMap.get(userName).values());
                }
            }

            return result;
        }

        if (!k8sClusterSvcInfoMap.containsKey(createUser)){
            return null;
        }

        return new ArrayList<>(k8sClusterSvcInfoMap.get(createUser).values());
    }

    @Override
    public void putK8sPodInfo(String createUser, RepByPage<PodModel> podModelRepByPage) {

        if (podModelRepByPage.getTotalNum() == 0){
            return;
        }

        if (!k8sClusterPodInfoMap.containsKey(createUser)){
            k8sClusterPodInfoMap.put(createUser,new HashMap<>());
        }

        k8sClusterPodInfoMap.get(createUser).put(
                podModelRepByPage.getResult().get(0).getK8sClusterName(),
                podModelRepByPage);
    }

    @Override
    public List<RepByPage<PodModel>> getK8sPodInfo(String createUser) {

        if (StringUtils.equals(createUser,CnapCloudMgmtConstants.ADMIN_USER_NAME)){
            List<RepByPage<PodModel>> result = new ArrayList<>();
            if (!k8sClusterPodInfoMap.isEmpty()){

                for (String userName:k8sClusterPodInfoMap.keySet()){
                    result.addAll(k8sClusterPodInfoMap.get(userName).values());
                }
            }

            return result;
        }

        if (!k8sClusterPodInfoMap.containsKey(createUser)){
            return null;
        }

        return new ArrayList<>(k8sClusterPodInfoMap.get(createUser).values());
    }



    @Override
    public void putK8sWorkLoadInfo(String createUser, RepByPage<WorkLoadModel> workLoadModelRepByPage) {

        if (workLoadModelRepByPage.getTotalNum() == 0){
            return;
        }

        if (!k8sClusterWorkLoadInfoMap.containsKey(createUser)){
            k8sClusterWorkLoadInfoMap.put(createUser,new HashMap<>());
        }

        k8sClusterWorkLoadInfoMap.get(createUser).put(
                workLoadModelRepByPage.getResult().get(0).getK8sClusterName(),
                workLoadModelRepByPage);

    }

    @Override
    public List<RepByPage<WorkLoadModel>> getK8sWorkLoadInfo(String createUser) {

        if (StringUtils.equals(createUser,CnapCloudMgmtConstants.ADMIN_USER_NAME)){
            List<RepByPage<WorkLoadModel>> result = new ArrayList<>();
            if (!k8sClusterWorkLoadInfoMap.isEmpty()){

                for (String userName:k8sClusterNsInfoMap.keySet()){
                    result.addAll(k8sClusterWorkLoadInfoMap.get(userName).values());
                }
            }

            return result;
        }

        if (!k8sClusterWorkLoadInfoMap.containsKey(createUser)){
            return null;
        }

        return new ArrayList<>(k8sClusterWorkLoadInfoMap.get(createUser).values());
    }

    @Override
    public List<RepByPage<NameSpaceModel>> getK8sNsInfo(String createUser) {

        if (StringUtils.equals(createUser,CnapCloudMgmtConstants.ADMIN_USER_NAME)){
            List<RepByPage<NameSpaceModel>> result = new ArrayList<>();
            if (!k8sClusterNsInfoMap.isEmpty()){

                for (String userName:k8sClusterNsInfoMap.keySet()){
                    result.addAll(k8sClusterNsInfoMap.get(userName).values());
                }
            }

            return result;
        }

        if (!k8sClusterNsInfoMap.containsKey(createUser)){
            return null;
        }
        return new ArrayList<>(k8sClusterNsInfoMap.get(createUser).values());
    }

    @Override
    public void putK8sNsInfo(String createUser, RepByPage<NameSpaceModel> nameSpaceModelRepByPage) {

        if (nameSpaceModelRepByPage.getTotalNum() == 0){
            return;
        }

        if (!k8sClusterNsInfoMap.containsKey(createUser)){
            k8sClusterNsInfoMap.put(createUser,new HashMap<>());
        }

        k8sClusterNsInfoMap.get(createUser).put(
                nameSpaceModelRepByPage.getResult().get(0).getK8sClusterName(),
                nameSpaceModelRepByPage);
    }

    @Override
    public List<RepByPage<NodeModel>> getK8sNodeInfo(String createUser) {

        //管理员特殊处理，返回所有
        if (StringUtils.equals(createUser, CnapCloudMgmtConstants.ADMIN_USER_NAME)){

            List<RepByPage<NodeModel>> result = new ArrayList<>();
            if (!k8sClusterNodeInfoMap.isEmpty()) {
                for (String userName : k8sClusterNodeInfoMap.keySet()) {
                    result.addAll(k8sClusterNodeInfoMap.get(userName).values());
                }
            }

            return result;

        }


        if(!k8sClusterNodeInfoMap.containsKey(createUser)){
            return null;
        }
        return new ArrayList<>(k8sClusterNodeInfoMap.get(createUser).values());
    }

    @Override
    public RepByPage<NodeModel> getK8sNodeInfoByClusterName(String createUser, String k8sClusterName) {

        if (StringUtils.isEmpty(createUser)||StringUtils.isEmpty(k8sClusterName)){
            return new RepByPage<>();
        }

        if (k8sClusterNodeInfoMap.isEmpty()){
            return new RepByPage<>();
        }

        if (!k8sClusterNodeInfoMap.containsKey(createUser)){
            return new RepByPage<>();
        }

        return k8sClusterNodeInfoMap.get(createUser).get(k8sClusterName);
    }

    /**
     * 放置node信息
     * @param createUser
     * @param nodeModelRepByPage
     */
    @Override
    public void putK8sNodeInfo(String createUser, RepByPage<NodeModel> nodeModelRepByPage) {

        if (nodeModelRepByPage.getTotalNum() == 0){
            return;
        }

        if (!k8sClusterNodeInfoMap.containsKey(createUser)){
            k8sClusterNodeInfoMap.put(createUser,new HashMap<>());
        }

        k8sClusterNodeInfoMap.get(createUser).put(
                nodeModelRepByPage.getResult().get(0).getK8sClusterName(),
                nodeModelRepByPage);

    }

    /**
     *
     * @param k8sClusterName
     * @return
     */
    @Override
    public K8sClusterBasicModel getK8sBasicModel(String k8sClusterName) {
        K8sClusterBasicModel k8sClusterBasicModel = k8sClusterBasicModelMap.get(k8sClusterName);
        if (k8sClusterBasicModel == null){
            k8sClusterBasicModel = multiCloudMgmtService.getK8sClusterInfoByName(k8sClusterName);
            if (k8sClusterBasicModel != null){
                putK8sBasicModel(k8sClusterName,k8sClusterBasicModel);
            }
        }

        return k8sClusterBasicModel;
    }

    /**
     * 
     * @param k8sClusterName
     * @param k8sClusterBasicModel
     */
    @Override
    public void putK8sBasicModel(String k8sClusterName, K8sClusterBasicModel k8sClusterBasicModel) {
        k8sClusterBasicModelMap.put(k8sClusterName,k8sClusterBasicModel);
    }

    /**
     *
     * @param k8sClusterIp
     * @param k8sClient
     */
    @Override
    public void putK8sClient(String k8sClusterIp, KubernetesClient k8sClient) {
        k8sClusterClientMap.put(k8sClusterIp,k8sClient);
    }

    /**
     *
     * @param k8sClusterIp
     * @return
     */
    @Override
    public KubernetesClient getK8sClient(String k8sClusterIp) {
        return k8sClusterClientMap.get(k8sClusterIp);
    }

    /**
     *
     * @param k8sClusterIp
     */
    @Override
    public void removeK8sClient(String k8sClusterIp) {
        k8sClusterClientMap.remove(k8sClusterIp);
    }

    /**
     *
     * @return
     */
    @Override
    public List<String> getK8sIps() {
        return new ArrayList<>(k8sClusterClientMap.keySet());
    }

    /**
     *
     * @param k8sClusterName
     * @param podModelMap
     */
    @Override
    public void putK8sPodModels(String k8sClusterName, Map<String, List<PodModel>> podModelMap) {
        
    }

    /**
     *
     * @param k8sClusterName
     * @return
     */
    @Override
    public List<PodModel> getK8sPodModels(String userName,String k8sClusterName) {

        if ((k8sClusterPodInfoMap == null)
                ||(k8sClusterPodInfoMap.get(userName) == null)
                ||(k8sClusterPodInfoMap.get(userName).get(k8sClusterName) == null)){
            return null;
        }
        return k8sClusterPodInfoMap.get(userName).get(k8sClusterName).getResult();
    }

    /**
     *
     * @param svcId
     */
    @Override
    public void putVmCreateSvc(String svcId) {

        vmCreateSvcInfo.put(svcId,(new Date()).getTime());
    }

    /**
     *
     * @param svcId
     * @return
     */
    @Override
    public long getVmCreateTime(String svcId) {

        if (vmCreateSvcInfo.containsKey(svcId)){
            return vmCreateSvcInfo.get(svcId);
        }

        return -1L;
    }

    /**
     *
     * @param svcId
     */
    @Override
    public void delVmCreate(String svcId) {
        try {
            vmCreateSvcInfo.remove(svcId);
        }catch (Exception e){
            LOGGER.error("delVmCreate fail svcId={}",svcId,e);
        }
    }

    /**
     *
     * @return
     */
    @Override
    public List<String> getAllVmCreateSvcId() {

        return new ArrayList<>(vmCreateSvcInfo.keySet());
    }
}
